ulong DecompressData(uint nStartAddr){

       //Chrono Trigger Decompression Routine

       //Reverse engineered by Michael Springer (evilpeer@hotmail.com)

       bool bCarryFlag = false;

       ushort nCompressedSize = (ushort) (RomData[nStartAddr] | (RomData[nStartAddr + 1] << 8));;

       uint nBytePos = nStartAddr + 2;

       uint nByteAfter = nBytePos + nCompressedSize;

       byte nBitCtr;

       byte nCurByte;

       byte nMem0D;

       uint nWorkPos = 0;

       bool bSmallerBitWidth = false;

 

       if((RomData[nByteAfter] & 0xC0) != 0){

              bSmallerBitWidth = true;

       }

 

       //C3/076B:    A908          LDA #$08

       //C3/076D:    850B          STA nBitCtr

       nBitCtr = 8;

       while(true){

              //C3/076F:    E409          CPX nByteAfter

              //C3/0771:    F056          BEQ $07C9

              if(nBytePos == nByteAfter){

                     //C3/07C9:    BD0000        LDA $0000,X

                     nCurByte = RomData[nBytePos];

                     //C3/07CC:    293F          AND #$3F

                     nCurByte &= 0x3F;

                     //C3/07CE:    F012          BEQ $07E2

                     if(nCurByte == 0){

                           //C3/07E2:    4CA408        JMP $08A4

                           return nWorkPos;

                     }

                     //C3/07D0:    850B          STA nBitCtr

                     nBitCtr = nCurByte;

                     //C3/07D2:    C221          REP #$21

                     bCarryFlag = false;

                     //C3/07D4:    BD0100        LDA $0001,X

                     //C3/07D7:    6500          ADC $00

                     //C3/07D9:    8509          STA nByteAfter

                     nByteAfter = (uint) (nStartAddr + ((RomData[nBytePos + 2] << 8) | RomData[nBytePos + 1]));

                     //C3/07DB:    E8            INX

                     //C3/07DC:    E8            INX

                     //C3/07DD:    E8            INX

                     nBytePos += 3;

                     //C3/07DE:    E220          SEP #$20

                     //C3/07E0:    808D          BRA $076F

              }

              else{

                     //C3/0773:    BD0000        LDA $0000,X

                     nCurByte = RomData[nBytePos];

                     //C3/0776:    F0AB          BEQ $0723

                     if(nCurByte == 0){

                           //C3/0723:    BD0100        LDA $0001,X

                           nCurByte = RomData[nBytePos + 1];

                           //C3/0726:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/072A:    BD0200        LDA $0002,X

                           nCurByte = RomData[nBytePos + 2];

                           //C3/072D:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/0731:    BD0300        LDA $0003,X

                           nCurByte = RomData[nBytePos + 3];

                           //C3/0734:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/0738:    BD0400        LDA $0004,X

                           nCurByte = RomData[nBytePos + 4];

                           //C3/073B:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/073F:    BD0500        LDA $0005,X

                           nCurByte = RomData[nBytePos + 5];

                           //C3/0742:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/0746:    BD0600        LDA $0006,X

                           nCurByte = RomData[nBytePos + 6];

                           //C3/0749:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/074D:    BD0700        LDA $0007,X

                           nCurByte = RomData[nBytePos + 7];

                           //C3/0750:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/0754:    BD0800        LDA $0008,X

                           nCurByte = RomData[nBytePos + 8];

                           //C3/0757:    8F802100      STA $002180

                           WorkingBuffer[nWorkPos++] = nCurByte;

                           //C3/075B:    C221          REP #$21

                           bCarryFlag = false;

                           //C3/075D:    8A            TXA

                           //C3/075E:    690900        ADC #$0009

                           //C3/0761:    AA            TAX

                           nBytePos += 9;

                           //C3/0762:    98            TYA

                           //C3/0763:    690800        ADC #$0008

                           //C3/0766:    A8            TAY

                           //C3/0767:    E220          SEP #$20

                           //C3/0769:    8004          BRA $076F

                     }

                     else{

                           //C3/0778:    E8            INX

                           nBytePos++;

                           //C3/0779:    4A            LSR A

                           //C3/077A:    850D          STA $0D

                           if((nCurByte & 0x01) == 1){

                                  bCarryFlag = true;

                           }

                           else{

                                  bCarryFlag = false;

                           }

                           nCurByte >>= 1;

                           nMem0D = nCurByte;

                           //C3/077C:    B01C          BCS $079A

                           if(bCarryFlag){

                                  CTCopyBytes(ref nBytePos, ref nWorkPos, bSmallerBitWidth);

                           }

                           else{

                                  //C3/077E:    BD0000        LDA $0000,X

                                  nCurByte = RomData[nBytePos];

                                  //C3/0781:    8F802100      STA $002180

                                  WorkingBuffer[nWorkPos++] = nCurByte;

                                  //C3/0785:    C8            INY

                                  //C3/0786:    E8            INX

                                  nBytePos++;

                           }

                           while(true){

                                  //C3/0787:    C60B          DEC nBitCtr

                                  nBitCtr--;

                                  //C3/0789:    F0E0          BEQ $076B

                                  if(nBitCtr == 0){

                                         nBitCtr = 8;

                                         break;

                                  }

                                  else{

                                         //C3/078B:    460D          LSR $0D

                                         if((nMem0D & 0x01) == 1){

                                                bCarryFlag = true;

                                         }

                                         else{

                                                bCarryFlag = false;

                                         }

                                         nMem0D >>= 1;

                                         //C3/078D:    B00B          BCS $079A

                                         if(bCarryFlag){

                                                CTCopyBytes(ref nBytePos, ref nWorkPos, bSmallerBitWidth);

                                         }

                                         else{

                                                //C3/078F:    BD0000        LDA $0000,X

                                                nCurByte = RomData[nBytePos];

                                                //C3/0792:    8F802100      STA $002180

                                                WorkingBuffer[nWorkPos++] = nCurByte;

                                                //C3/0796:    C8            INY

                                                //C3/0797:    E8            INX

                                                nBytePos++;

                                                //C3/0798:    80ED          BRA $0787

                                         }

                                  }

                           }

                     }

              }

       }

}

 

void CTCopyBytes(ref uint nBytePos, ref uint nWorkPos, bool bSmallerBitWidth){

       byte nBytesCopyNum;

       ushort nBytesCopyOff;

 

       //C3/079A:    BD0100        LDA $0001,X

       nBytesCopyNum = RomData[nBytePos + 1];

       //C3/079D:    4A            LSR A

       //C3/079E:    4A            LSR A

       //C3/079F:    4A            LSR A

       if(bSmallerBitWidth){

              nBytesCopyNum >>= 3;

       }

       else{

              nBytesCopyNum >>= 4;

       }

       //C3/07A0:    1A            INC A

       //C3/07A1:    1A            INC A

       nBytesCopyNum += 2;

       //C3/07A2:    850F          STA $0F

       //C3/07A4:    C220          REP #$20

       //C3/07A6:    BD0000        LDA $0000,X

       nBytesCopyOff = (ushort) ((RomData[nBytePos + 1] << 8) | RomData[nBytePos]);

       //C3/07A9:    29FF07        AND #$07FF

       //C3/07AC:    8515          STA $15

       if(bSmallerBitWidth){

              nBytesCopyOff &= 0x07FF;

       }

       else{

              nBytesCopyOff &= 0x0FFF;

       }

       //C3/07AE:    98            TYA

       //C3/07AF:    38            SEC

       //C3/07B0:    E515          SBC $15

       //C3/07B2:    8615          STX $15

       //C3/07B4:    AA            TAX

       //C3/07B5:    A50F          LDA $0F

       //C3/07B7:    8B            PHB

       //C3/07B8:    547E7E        MVN $7E,$7E

       for(int i = 0; i < nBytesCopyNum + 1; i++){

              WorkingBuffer[nWorkPos + i] = WorkingBuffer[nWorkPos - nBytesCopyOff + i];

       }

       nWorkPos += (uint) (nBytesCopyNum + 1);

       //C3/07BB:    AB            PLB

       //C3/07BC:    98            TYA

       //C3/07BD:    8F812100      STA $002181

       //C3/07C1:    E220          SEP #$20

       //C3/07C3:    A615          LDX $15

       //C3/07C5:    E8            INX

       //C3/07C6:    E8            INX

       nBytePos += 2;

       //C3/07C7:    80BE          BRA $0787

}